﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace XFSale.Lib
{
    using DictMetaSet = Dictionary<string, DictMeta>;
    using PackMetaSet = Dictionary<string, PackMeta>;

    public static class Log
    {
        public const int LOGTO_TUXEDO = 0;
        public const int LOGTO_STDOUT = 1;
        public const int LOGTO_STDERR = 2;
        public const int LOGTO_FILE = 3;

        public const int LOGLVL_VERBOSE = 0;
        public const int LOGLVL_DEBUG = 1;
        public const int LOGLVL_INFO = 2;
        public const int LOGLVL_WARN = 3;
        public const int LOGLVL_ERROR = 4;

        private static int _logTo = LOGTO_FILE;
        private static int _logLevel = LOGLVL_VERBOSE;
        private static string _logFile = string.Empty;
        private static bool _logReset = false;

        public static int LogTo
        {
            get { return Log._logTo; }
            set { Log._logTo = value; }
        }

        public static int LogLevel
        {
            get { return Log._logLevel; }
            set { Log._logLevel = value; }
        }

        public static string LogFile
        {
            get { return Log._logFile; }
            set { Log._logFile = value; }
        }

        public static bool LogReset
        {
            get { return Log._logReset; }
            set { Log._logReset = value; }
        }

        public static void LogVerbose(string fmt, params object[] args)
        {
            _Log(LOGLVL_VERBOSE, LogTo, LogFile, string.Format(fmt, args));
        }

        public static void LogDebug(string fmt, params object[] args)
        {
            _Log(LOGLVL_DEBUG, LogTo, LogFile, string.Format(fmt, args));
        }

        public static void LogInfo(string fmt, params object[] args)
        {
            _Log(LOGLVL_INFO, LogTo, LogFile, string.Format(fmt, args));
        }

        public static void LogWarn(string fmt, params object[] args)
        {
            _Log(LOGLVL_WARN, LogTo, LogFile, string.Format(fmt, args));
        }

        public static void LogError(string fmt, params object[] args)
        {
            _Log(LOGLVL_ERROR, LogTo, LogFile, string.Format(fmt, args));
        }

        public static void LogThrowError(string fmt, params object[] args)
        {
            string errMsg = string.Format(fmt, args);
            _Log(LOGLVL_ERROR, LogTo, LogFile, errMsg);
            throw new Error(errMsg);
        }

        public static void LogRequest()
        {
            _LogPack(LOGLVL_INFO, LogTo, LogFile, App.Request);
        }

        public static void LogResponse()
        {
            _LogPack(LOGLVL_INFO, LogTo, LogFile, App.Response);
        }

        public static void LogPackMeta()
        {
            _LogPackMeta(LOGLVL_VERBOSE, LogTo, LogFile, App.PackMeta);
        }

        public static void LogDictMeta()
        {
            _LogDictValue(LOGLVL_VERBOSE, LogTo, LogFile, App.DictMeta);
        }

        //----------------------------------------------
        //	写数据包日志
        //----------------------------------------------
        private static void _LogPack(int level, int to, string file, Pack pack)
        {
            DictMeta dm = null;
            string val = null;
            int pos = 0;
            StringBuilder txt = new StringBuilder();

            txt.Append("\r\n");
            foreach (PackItem item in pack.HeadMeta.packItems)
            {
                dm = App.DictMeta[item.itemName.Trim().ToUpper()];
                val = StringUtil.BytesToStr(pack.PackData, pos, dm.itemLen);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", dm.itemName, val);
                pos += dm.itemLen;
            }

            txt.Append("\r\n");
            foreach (PackItem item in pack.BaseMeta.packItems)
            {
                dm = App.DictMeta[item.itemName.Trim().ToUpper()];
                val = StringUtil.BytesToStr(pack.PackData, pos, dm.itemLen);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", dm.itemName, val);
                pos += dm.itemLen;
            }

            for (int i = 0; i < pack.RecordCount; i++)
            {
                txt.Append("\r\n");
                foreach (PackItem item in pack.RecordMeta.packItems)
                {
                    dm = App.DictMeta[item.itemName.Trim().ToUpper()];
                    val = StringUtil.BytesToStr(pack.PackData, pos, dm.itemLen);
                    txt.AppendFormat("{0,-18}:[{1}]\r\n", dm.itemName, val);
                    pos += dm.itemLen;
                }
                pos += Pack.PACKRECORD_SEP.Length;
            }


            _Log(level, to, file, txt.ToString());
            txt = null;
        }

        //----------------------------------------------
        //	写数据包信息日志
        //----------------------------------------------
        private static void _LogPackMeta(int level, int to, string file, PackMetaSet meta)
        {
            StringBuilder txt = new StringBuilder();
            foreach (PackMeta pm in meta.Values)
            {
                txt.Append("-------------数据包信息--------------------\r\n");
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ServiceCode", pm.serviceCode);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "PackType", pm.packType);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "PackDesc", pm.packDesc);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "RecordType", pm.recordType);

                foreach (PackItem pi in pm.packItems)
                {
                    txt.Append("\r\n");
                    txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemID", pi.itemID);
                    txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemName", pi.itemName);
                    txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemOrder", pi.itemOrder);
                }
            }
            _Log(level, to, file, txt.ToString());
            txt = null;
        }

        //----------------------------------------------
        //	写字典取值日志
        //----------------------------------------------
        private static void _LogDictValue(int level, int to, string file, DictMetaSet dict)
        {
            StringBuilder txt = new StringBuilder();
            foreach (DictMeta dm in dict.Values)
            {
                txt.Append("-------------字典信息--------------------\r\n");
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemID", dm.itemID);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemName", dm.itemName);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemType", dm.itemType);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemScale", dm.itemScale);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemPrecise", dm.itemPrecise);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemDesc", dm.itemDesc);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemClass", dm.itemClass);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemVerify", dm.itemVerify);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemDefault", dm.itemDefault);
                txt.AppendFormat("{0,-18}:[{1}]\r\n", "IieldName", dm.fieldName);

                foreach (DictValue dv in dm.valueItems)
                {
                    txt.Append("\r\n");
                    txt.AppendFormat("{0,-18}:[{1}]\r\n", "ItemValue", dv.itemValue);
                    txt.AppendFormat("{0,-18}:[{1}]\r\n", "ValueDesc", dv.valueDesc);
                }
            }
            _Log(level, to, file, txt.ToString());
            txt = null;
        }

        //----------------------------------------------
        //	写系统日志
        //----------------------------------------------
        private static void _Log(int level, int to, string file, string str)
        {
            StreamWriter writer = null;

            if (LogLevel > level)
                return;

            switch (to)
            {
                case LOGTO_TUXEDO:
                    break;

                case LOGTO_STDOUT:
                    Console.Out.WriteLine(str);
                    break;

                case LOGTO_STDERR:
                    Console.Error.WriteLine(str);
                    break;

                case LOGTO_FILE:
                    try
                    {
                        writer = new StreamWriter(_logFile, true);
                        writer.WriteLine(str);
                    }
                    catch
                    {
                        Log.LogThrowError("写入日志文件失败");
                    }
                    finally
                    {
                        writer.Close();
                    }
                    break;

                default:
                    Log.LogThrowError("不支持的日志输出选项");
                    break;
            }
        }
    }
}
